package com.ziq.zcamp.view

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.ViewConfiguration
import android.widget.FrameLayout
import androidx.core.view.NestedScrollingChild2
import androidx.core.view.NestedScrollingChild3
import androidx.core.view.NestedScrollingChildHelper
import androidx.core.view.ViewCompat


class NestedScrollingFrameLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr), NestedScrollingChild2, NestedScrollingChild3 {

    private val mTouchSlop : Int

    init {
        isNestedScrollingEnabled = true

        val vc = ViewConfiguration.get(context)
        mTouchSlop = vc.scaledTouchSlop
    }

    private var mDownMotionX = 0
    private var mDownMotionY = 0
    private var mLastMotionY = 0
    private val mScrollOffset = IntArray(2)
    private val mScrollConsumed = IntArray(2)
    private var isDragging = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.getActionMasked()) {
            MotionEvent.ACTION_DOWN -> {
                isDragging = false
                mDownMotionX = event.rawX.toInt()
                mDownMotionY = event.rawY.toInt()

                mLastMotionY = event.rawY.toInt()
            }
            MotionEvent.ACTION_MOVE -> {
                val x = event.rawX.toInt()
                val y = event.rawY.toInt()
                var deltaY = mLastMotionY - y
                mLastMotionY = y

                val dx: Int = x - mDownMotionX
                val dy: Int = y - mDownMotionY
                if((Math.abs(dy) > Math.abs(dx)) || isDragging) {
                    isDragging = true
                    parent?.requestDisallowInterceptTouchEvent(true)
                    if (startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_TOUCH) && dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset, ViewCompat.TYPE_TOUCH)) {
                        deltaY -= mScrollConsumed[1]
                    }
                    mScrollConsumed[0] = 0
                    mScrollConsumed[1] = 0
                    dispatchNestedScroll(0, deltaY, 0, deltaY, mScrollOffset, ViewCompat.TYPE_TOUCH, mScrollConsumed)
                } else {
                    parent?.requestDisallowInterceptTouchEvent(false)
                }
            }
            MotionEvent.ACTION_UP -> {
                //停止嵌套滑动
                parent?.requestDisallowInterceptTouchEvent(false)
                stopNestedScroll(ViewCompat.TYPE_TOUCH)
            }
            MotionEvent.ACTION_CANCEL -> {
                parent?.requestDisallowInterceptTouchEvent(false)
                stopNestedScroll(ViewCompat.TYPE_TOUCH)
            }

        }
        return true
    }

    private var mScrollingChildHelper: NestedScrollingChildHelper? = null
    private fun getScrollingChildHelper(): NestedScrollingChildHelper? {
        if (mScrollingChildHelper == null) {
            mScrollingChildHelper = NestedScrollingChildHelper(this)
        }
        return mScrollingChildHelper
    }


    // NestedScrollingChild
    override fun setNestedScrollingEnabled(enabled: Boolean) {
        getScrollingChildHelper()!!.isNestedScrollingEnabled = enabled
    }

    override fun isNestedScrollingEnabled(): Boolean {
        return getScrollingChildHelper()!!.isNestedScrollingEnabled
    }

    override fun startNestedScroll(axes: Int): Boolean {
        return getScrollingChildHelper()!!.startNestedScroll(axes)
    }

    override fun startNestedScroll(axes: Int, type: Int): Boolean {
        return getScrollingChildHelper()!!.startNestedScroll(axes, type)
    }

    override fun stopNestedScroll() {
        getScrollingChildHelper()!!.stopNestedScroll()
    }

    override fun stopNestedScroll(type: Int) {
        getScrollingChildHelper()!!.stopNestedScroll(type)
    }

    override fun hasNestedScrollingParent(): Boolean {
        return getScrollingChildHelper()!!.hasNestedScrollingParent()
    }

    override fun hasNestedScrollingParent(type: Int): Boolean {
        return getScrollingChildHelper()!!.hasNestedScrollingParent(type)
    }

    override fun dispatchNestedScroll(
        dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int,
        dyUnconsumed: Int, offsetInWindow: IntArray?
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedScroll(
            dxConsumed, dyConsumed,
            dxUnconsumed, dyUnconsumed, offsetInWindow
        )
    }

    override fun dispatchNestedScroll(
        dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int,
        dyUnconsumed: Int, offsetInWindow: IntArray?, type: Int
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedScroll(
            dxConsumed, dyConsumed,
            dxUnconsumed, dyUnconsumed, offsetInWindow, type
        )
    }

    override fun dispatchNestedScroll(
        dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int,
        dyUnconsumed: Int, offsetInWindow: IntArray?, type: Int, consumed: IntArray
    ) {
        getScrollingChildHelper()!!.dispatchNestedScroll(
            dxConsumed, dyConsumed,
            dxUnconsumed, dyUnconsumed, offsetInWindow, type, consumed
        )
    }

    override fun dispatchNestedPreScroll(
        dx: Int,
        dy: Int,
        consumed: IntArray?,
        offsetInWindow: IntArray?
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
    }

    override fun dispatchNestedPreScroll(
        dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?,
        type: Int
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedPreScroll(
            dx, dy, consumed, offsetInWindow,
            type
        )
    }

    override fun dispatchNestedFling(
        velocityX: Float,
        velocityY: Float,
        consumed: Boolean
    ): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedFling(velocityX, velocityY, consumed)
    }

    override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean {
        return getScrollingChildHelper()!!.dispatchNestedPreFling(velocityX, velocityY)
    }

}